#include "log_system.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

static char *action_string[LOG_NUMS]={
    "登录",
    "登出",
    "添加",
    "删除",
    "更新",
};

/*
** 功能：初始化日志链表
*/ 
void log_init(void)
{
	if( log_head != NULL )
		return ;
	
	log_head = calloc(1, sizeof(LogEntry));
	if( log_head == NULL )
	{
		perror("log_init calloc fail");
		return ;
	}
	log_head->next = log_head;
	log_head->prev = log_head;
}



/*
** 功能：添加日志
** action：操作类型
** user：操作用户
** item_id：货物id
** desc：操作说明
*/ 
void log_add(LogAction action, const char *user, int item_id, const char *desc)
{
	// 检查参数有效性 user, desc
	if( user == NULL || desc == NULL )
	{
		fprintf(stderr, "日志参数错误\n");
		return ;
	}
	
	// 创建日志条目
	LogEntry *new = calloc(1, sizeof(LogEntry));
	if(new == NULL)
	{
		perror("log_add() calloc fail");
		return ;
	}
	
	
	char buf[50] = {0};
	time_t rawtime = time(NULL);	//获取当前系统时间
    struct tm *info = localtime( &rawtime );	//把当前时间转成本地的日期结构
    strftime(buf, 50, "[%Y年-%m月-%e日 %H:%M:%S]", info);//以年月日_时分秒的形式表示当前时间
  
	strncpy(new->date, buf, 50-1);
	new->action = action;
	strncpy(new->username, user, sizeof(new->username)-1);
	new->item_id = item_id;
	strncpy(new->description, desc, sizeof(new->description)-1);
	
	// 添加到日志列表（访问时向后遍历，最新日志在前面）
	new->prev = log_head;
	new->next = log_head->next;
	log_head->next->prev = new;
	log_head->next = new;
}

/*
** 功能：保存日志为文本
** filename：文件名
*/ 
void log_save_text(const char *filename)
{
	FILE *fp = fopen(filename, "w");
	if( fp == NULL )
	{
		perror("log_save() fail");
		return ;
	}
	
	LogEntry *tmp = log_head->prev;
	while( tmp != log_head )
	{
		fprintf(fp, "%s %s %s %d %s\n", 
					tmp->date, 
					action_string[tmp->action],
					tmp->username,
					tmp->item_id,
					tmp->description
					);
	
		tmp = tmp->prev;
	}
	fclose(fp);
}


/*
** 功能：加载日志文本
** filename：文件名
*/ 
void log_load_text(const char *filename)
{
	FILE *fp = fopen(filename, "r");
	if( fp == NULL )
	{
		perror("log_load_text() fail");
		return ;
	}
	
	char date[50] = {0};
	char action[10] = {0};
	char user[32] = {0};
	int item_id = 0; 
	char desc[128] = {0};
	while( fscanf(fp, "%s %s %s %d %s", date, action, user, &item_id, desc) == 5 )
	{
		// 创建日志条目
		LogEntry *new = calloc(1, sizeof(LogEntry));
		if(new == NULL)
		{
			perror("log_add() calloc fail");
			return ;
		}
		
		strncpy(new->date, date, sizeof(new->date)-1);
		for(int i=0; i<LOG_NUMS; i++)
		{
			if( strcmp(action, action_string[i]) )
				new->action = i;
		}
		strncpy(new->username, user, sizeof(new->username)-1);
		new->item_id = item_id;
		strncpy(new->description, desc, sizeof(new->description)-1);
		
		// 添加到日志列表（访问时向后遍历，最新日志在前面）
		new->prev = log_head;
		new->next = log_head->next;
		log_head->next->prev = new;
		log_head->next = new;
	}
	fclose(fp);
}

/*
** 功能：保存日志为二进制
** filename：文件名
*/ 
void log_save_bin(const char *filename)
{
	FILE *fp = fopen(filename, "wb");
	if( fp == NULL )
	{
		perror("log_save() fail");
		return ;
	}
	
	LogEntry *tmp = log_head->prev;
	while( tmp != log_head )
	{
		fwrite(tmp, sizeof(LogEntry), 1, fp);
	
		tmp = tmp->prev;
	}
	fclose(fp);
}

/*
** 功能：加载日志二进制
** filename：文件名
*/ 
void log_load_bin(const char *filename)
{
	FILE *fp = fopen(filename, "rb");
	if( fp == NULL )
	{
		perror("log_load_text() fail");
		return ;
	}
	
	// 从文件读取数据，加载到链表
	LogEntry tmp; 
	while( fread(&tmp, sizeof(LogEntry), 1, fp) == 1 )
	{
		LogEntry *new = malloc(sizeof(LogEntry));
		memcpy(new, &tmp, sizeof(LogEntry));
		
		printf("%s %d %s %d %s\n", new->date, new->action, new->username, new->item_id, new->description);
		// 添加到日志列表（访问时向后遍历，最新日志在前面）
		new->prev = log_head;
		new->next = log_head->next;
		log_head->next->prev = new;
		log_head->next = new;
	}
	
	fclose(fp);
}

/*
** 功能：显示最近N条记录
** count：多少条
*/ 
void log_show_recent(int count)
{
	printf("\n*******最近的%d条操作日志*******\n", count);
	printf("%-30s | %-10s | %-32s | %-8s | 操作描述 \n",
			"日期", "类型", "用户名", "货物ID");
	
	LogEntry *tmp = log_head->prev;
	for( int i=0; i<count && tmp != log_head; i++, tmp = tmp->prev )
	{
		printf("%-20s | %-10s | %-32s | %-8d | %-60s\n",
					tmp->date, 
					action_string[tmp->action],
					tmp->username,
					tmp->item_id,
					tmp->description
					);
	}
}


/*
** 功能：清空日志链表
** count：多少条
*/ 
void log_cleanup(void)
{
	LogEntry *tmp = log_head->next;
	LogEntry *del = NULL;
	while( tmp != log_head )
	{
		del = tmp;
		tmp = tmp->next;
		free(del);
	}
	free(log_head);
	log_head = NULL;
}

